/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#pragma once

#include "引擎数据类型.h"
#include "core/设备内存缓存.h"
#include "core/shader_std.h"
#include "core/属性.h"

#include "向量.h"
#include "帧缓存.h"


#include <Windows.h>


typedef void* T_渲染通道;

struct S_Mesh;



typedef struct {
	S_板载缓存**	m_参数槽;
	S_纹理**		m_纹理槽;
	uint8*			m_绑定位置;

	uint16			m_参数数量;
	uint16			m_纹理数量;

}S_GPU参数布局;

typedef struct {
	void**	m_参数槽;
	uint32* m_参数类型;
	uint8*  m_绑定位置;
	uint16*	m_绑定数量;

	uint16	m_参数数量;
}S_GPU参数槽;

typedef struct {
	vec3			m_深度偏移;

	S_板载缓存*		m_视图投影矩阵;
	S_板载缓存*		m_相机矩阵;

	S_Viewport*		m_视口;
	S_Rect2D*		m_裁剪;
	S_结构对象指针	m_GPU参数;

	
	S_GPU内存块索引* m_间接;

	float32			m_线宽;

	uint32          m_顶点内存偏移;
	uint32          m_顶点数量;
	uint32          m_索引内存数量;
	uint32          m_索引内存偏移;
	uint32			m_实例数量;
	uint32			m_实例偏移;
	uint32			m_间接偏移;
	uint32			m_间接数量;


	//！！！！！！！！！！！！！！！！ 废弃 
	S_板载缓存*		m_间接绘制;

}S_渲染参数;



typedef struct {
	S_结构对象指针	m_设备;
	S_结构对象指针	m_物理设备;
}S_绘图设备;

typedef struct {
	uint64          m_Type;
	uint64          m_线程数量;
	S_结构对象指针  m_逻辑设备;
	S_结构对象指针* m_命令缓存;
}S_子集绘图命令;




struct S_绘图框架 {

	bool				m_是否暂停;
	std::vector<S_设备>	m_设备;
	E_绘图API			m_Type;
	S_设备环境          m_Ctx;
	//void*               m_绘图设备配置;




	static S_子集绘图命令* g_资源加载管道;



	S_绘图框架();


	virtual S_协处理设备	f_取物理设备(uint8 id) { return {}; }


	virtual S_协处理设备	f_创建图形逻辑设备(S_协处理设备& dev, bool 是否有光追支持) { return { 0, -1 }; }
	virtual S_协处理设备	f_创建计算逻辑设备(S_协处理设备& dev) { return { 0, -1 }; }

	virtual S_协处理设备	f_创建命令缓存(S_结构对象指针 dev) { return { 0, -1 }; }
	virtual S_协处理设备	f_创建图形线管(S_结构对象指针 dev) { return { 0, -1 }; }

	virtual bool			f_创建命令缓存池(S_协处理设备& dev) { return false; }
	virtual bool			f_创建命令缓存(S_协处理设备& dev, uint32 池ID, uint32 num = 1) { return false; }
	virtual bool			f_创建同步围栏(S_协处理设备& 逻辑dev) { return false; }
	


	virtual bool	f_创建窗口绘制面(void* 绘图设备, HINSTANCE& hInstance, HWND& hWnd, ivec2 size, E_MS次数 采样) { return false; }
	virtual void	f_重置交换链(void* 绘图设备, ivec2 size, E_MS次数 采样) {}

	virtual bool	f_创建描述符() { return false; }
	virtual bool	f_创建深度模板视图(ivec2 size) { return false; }
	virtual void	f_重置视口(void* 绘图设备, ivec2 size, E_MS次数 采样);
	virtual void	f_alloc(void* 绘图设备配置) {}
	virtual void	f_End(void* 绘图设备配置) {}


	virtual	void*			f_get设备() { return 0; }
	virtual	void*			f_get命令列表() { return 0; }
	virtual	void*			f_get环境() { return 0; }


	//virtual uint32			f_get绘制方式(E_绘制方式 方式) = 0;


};









struct S_着色器加载参数 {
	std::string path;
	E_着色阶段	阶段;
};

struct S_着色器常量推送创建参数 {
	uint32 阶段;
	uint32 偏移;
	uint32 字节数;
};

struct S_着色器创建参数 {
	uint32			m_绑定位置;
	uint32			m_着色阶段;
	E_板载缓存类型	m_参数类型;
};

struct S_着色顶点输入参数 {
	uint32		m_绑定位置;
	uint32		m_元素大小;
	uint32		m_输入数据类型;
	E_数据格式	m_数据格式;
};

struct S_着色索引输入参数 {
	uint32		m_元素大小;
	E_数据格式	m_数据格式;
};


struct S_线管创建配置 {
	std::vector<S_着色器创建参数>         m_参数布局;
	std::vector<S_着色顶点输入参数>       m_顶点配置;
	std::vector<S_着色器加载参数>         m_Paths;
	std::vector<S_着色器常量推送创建参数> m_常量偏移和字节数;
};


struct S_着色 {
	int32 m_ShaderIndex;

	S_着色(const std::string& name);

	virtual void	f_init着色参数布局(const S_线管创建配置& 参数配置) = 0;
	virtual void	f_alloc参数设置(S_结构对象指针* 描述集列表) = 0;
	virtual void	f_销毁着色器(uint32 id) {};
};


struct S_节点实例着色器 : public S_着色 {
	S_节点实例着色器() :S_着色("节点实例着色器") {};
	virtual void	f_init着色参数布局(const S_线管创建配置& 参数配置) {};
	virtual void	f_alloc参数设置(S_结构对象指针* 描述集列表) {};
};



struct S_线管创建参数 {
	ivec2	m_视口大小;
	vec2	m_视口深度;
	
	ivec2	m_裁剪偏移;
	ivec2	m_裁剪大小;

	uint32		m_视口数量;
	E_绘制方式	m_绘制方式;
	E_填充模式	m_填充模式;
	E_混合模式	m_透明混合模式;
	E_混合模式	m_颜色混合模式;

	E_混合因子	m_源颜色混合因子;
	E_混合因子	m_目标颜色混合因子;
	E_混合因子	m_源透明通道因子;
	E_混合因子	m_目标透明通道因子;

	E_MS次数	m_采样;

	float32		m_深度偏移;

	bool	m_图元重启;
	//uint8	m_阶段数量;
	bool	m_启用深度测试;
	bool	m_启用写入深度;
	bool	m_启用深度边界;
	bool	m_启用混合;
	

	S_线管创建参数(ivec2 viewSize);
};


struct S_线管 {
	S_设备环境* m_Ctx;

	S_线管(const std::string& name);

	//E_着色阶段		m_着色阶段[6];
	virtual void f_创建线管(const S_线管创建参数& 参数, S_着色& shader) = 0;

};


Inline void f_df_init_GPU参数布局(S_GPU参数布局* layout) {
	layout->m_参数槽 = nullptr;
	layout->m_纹理槽 = nullptr;
	layout->m_绑定位置 = nullptr;

	layout->m_参数数量 = 0;
	layout->m_纹理数量 = 0;
	//layout->m_GPU参数set = 0;
}

typedef void(*fp_set材质GPU参数布局)(struct S_材质* mat, S_GPU参数布局& layout, uint16 网格属性缓存槽数量);
typedef void(*fp_set材质GPU参数配置)(struct S_材质* mat, void* ob, void* mesh, uint8 槽);
//typedef void(*fp_材质实例数量变更)(struct S_材质 mat, uint32 实例数量);
struct S_材质 {
	S_线管*			m_Pipeline;
	S_着色*			m_Shader;
	S_结构对象指针	m_GPU参数set;
	//S_板载缓存* m_光追材质;
	uint32		m_光追材质ID;
	
	S_设备环境*		m_Ctx;
	bool			m_深度遮挡;

	S_结构对象指针	m_并行计算GPU参数set;

	fp_set材质GPU参数配置	mf_GPU参数配置;
	
	
	S_材质(S_设备环境* ctx = nullptr);
	virtual S_材质* f_copy() { return nullptr; }

	//废弃
	fp_set材质GPU参数布局	mf_GPU材质槽更新 = nullptr;
};
typedef S_材质 t_GPU数据;



struct S_GPU计算 {
	S_设备环境	m_Ctx;
	S_线管*		m_Pipeline;
	S_着色*		m_Shader;

	S_结构对象指针			m_GPU参数set;
	uvec3					m_线程维度;
	fp_set材质GPU参数配置	mf_GPU参数配置;

	S_GPU计算(S_设备环境* ctx);
	virtual S_材质* f_copy() { return nullptr; }
};



Inline void f_alloc缓存槽(S_GPU参数布局* layout, uint16 num) {
	layout->m_参数数量 = num;

	if (layout->m_参数槽) free(layout->m_参数槽);
	if (layout->m_绑定位置) free(layout->m_绑定位置);
	layout->m_参数槽 = (S_板载缓存**)calloc(layout->m_参数数量, sizeof(S_板载缓存*));
	layout->m_绑定位置 = (uint8*)calloc(layout->m_参数数量, sizeof(uint8));
	
	for (uint32 i = 0; i < layout->m_参数数量; ++i) {
		layout->m_参数槽[i] = nullptr;
	}
	memset(layout->m_绑定位置, 0, layout->m_参数数量 * sizeof(uint8));
}
Inline void f_alloc纹理槽(S_GPU参数布局* layout, uint16 num) {
	layout->m_纹理槽 = (S_纹理**)calloc(num, sizeof(S_纹理*));
	layout->m_纹理数量 = num;

	for (uint32 i = 0; i < num; ++i) {
		layout->m_纹理槽[i] = nullptr;
	}
}
Inline void f_allocGPU参数缓存槽(S_GPU参数槽* layout, uint16 num) {
	layout->m_参数数量 = num;

	if (layout->m_参数槽) free(layout->m_参数槽);
	if (layout->m_绑定位置) free(layout->m_绑定位置);
	layout->m_参数槽 = (void**)calloc(layout->m_参数数量, sizeof(void*));
	layout->m_参数类型 = (uint32*)calloc(layout->m_参数数量, sizeof(uint32));
	layout->m_绑定位置 = (uint8*)calloc(layout->m_参数数量, sizeof(uint8));
	layout->m_绑定数量 = (uint16*)calloc(layout->m_参数数量, sizeof(uint16));

	memset(layout->m_参数槽, 0, layout->m_参数数量 * sizeof(void*));
	memset(layout->m_参数类型, 0, layout->m_参数数量 * sizeof(uint8));
	memset(layout->m_绑定位置, 0, layout->m_参数数量 * sizeof(uint8));
	memset(layout->m_绑定数量, 0, layout->m_参数数量 * sizeof(uint16));
}

Inline void f_release缓存槽(S_GPU参数布局* layout) {
	free(layout->m_参数槽);
	free(layout->m_绑定位置);
	layout->m_参数数量 = 0;
}
Inline void f_release纹理槽(S_GPU参数布局* layout) {
	free(layout->m_纹理槽);
	layout->m_纹理数量 = 0;
}
Inline void f_releaseGPU参数缓存槽(S_GPU参数槽* layout) {
	free(layout->m_参数槽);
	free(layout->m_绑定位置);
	layout->m_参数数量 = 0;
}



uint32 f_getVk绘制方式(E_绘制方式 方式, E_绘图API apiName = E_绘图API::E_Vulkan);
uint32 f_getVk填充方式(E_填充模式 方式, E_绘图API apiName = E_绘图API::E_Vulkan);
uint32 f_getVk混合模式(E_混合模式 模式);
uint32 f_getVk混合因子(E_混合因子 因子);

uint32	f_get数据格式(E_数据格式 格式, E_绘图API apiName = E_绘图API::E_Vulkan);









struct S_光追后端 {
	S_设备环境*		m_Ctx;
	S_线管*			m_光追管线;
	S_结构对象指针	m_GPU参数设置;
	S_GPU参数槽		m_参数布局;
	S_结构对象指针  m_绘图环境;

	static S_结构对象指针	m_加速结构创建命令缓存;
	static S_结构对象指针	m_渲染Fence;
	S_结构对象指针	m_渲染命令缓存;
	S_板载缓存*		m_顶层加速结构;
	S_纹理*			m_渲染纹理;


	S_板载缓存*	m_场景物体网格指针;
	S_板载缓存* m_几何属性;

	S_板载缓存* m_全局绑定参数指针;
	S_板载缓存* m_I32动态属性;
	S_板载缓存* m_F32动态属性;
	S_板载缓存* m_Vec2动态属性;
	S_板载缓存* m_Vec3动态属性;
	S_板载缓存* m_UVec2动态属性;
	S_板载缓存* m_UVec3动态属性;
	S_板载缓存*	m_UVec4动态属性;
	S_板载缓存* m_Mat44动态属性;
	S_板载缓存*	m_采样曲线属性;

	S_板载缓存* m_平行光缓冲区;
	S_板载缓存* m_点光源缓冲区;
	S_板载缓存* m_区域光缓冲区;
	S_板载缓存* m_聚光灯缓冲区;

	//S_Mesh* m_矩形区域光物体网格;
	S_Mesh*     m_区域光物体网格;



	static S_板载缓存* m_帧渲染信息;
	static S_板载缓存* m_材质;

	static float32* m_f32_gpu_mapptr;
	static int32*   m_i32_gpu_mapptr;
	static vec2*    m_vec2_gpu_mapptr;
	static vec3*    m_vec3_gpu_mapptr;
	static GLSL_RenderFrame* m_mapPtr_渲染帧数据;
	static uint8 g_光追列队;


	
	bool           m_渲染;
	bool		   m_重新编译线管;
	S_线管创建配置 m_线管创建配置信息;

	S_RayRenderAttr m_预览渲染参数;


	
	std::vector<S_纹理添加列队>      m_待加载纹理列队;
	static std::vector<S_MapPtrItem> G纹理;
	static std::mutex                g_资源分配内存锁;

	static E_离线渲染状态 g_渲染状态;

	S_光追后端();
	virtual ~S_光追后端();

	virtual void f_重置() = 0;
	virtual void f_添加底层加速结构(S_Mesh* me, uint32 id, E_物体类型 ObType) = 0;
	virtual void f_清除几何加速结构() = 0;
	virtual void f_分配底层加速结构数量(uint32 num) = 0;
	virtual void f_构建顶层加速结构(uint32 num) = 0;
	virtual void f_构建着色绑定列表() = 0;
	virtual void f_构建BVH() = 0;
	virtual void f_Rander(uvec2 viewSize) = 0;
	virtual void f_Rander(uvec2 viewSize, uint32 采样次数) = 0;

	virtual void f_更新实例变换(mat3X4 mat, uint32 id, uint32 ASID, uint8 DataID = 0, uint8 mask = 0xff) = 0;
	virtual void f_填充平行光参数(std::vector<S_LigthParallel>& 平行光参数组) = 0;

	virtual void f_重构材质线管() = 0;
	virtual void f_重载() {};
	virtual void* f_get纹理() { return nullptr; }
	virtual void  f_add纹理(S_纹理* 纹理, uint32 loc) { }
	virtual void  f_set纹理(S_纹理* 纹理) {  }
	virtual void  f_rem纹理(uint32 loc) {  }
	virtual uint16 f_get纹理数量() { return 0; }

	int32 f_需要要加载纹理数();
	//void  f_添加纹理计数(int32 num);

	static void f_重置渲染帧记录();
	static void f_递增渲染帧记录();

	void f_mapGPU参数();
	void f_unmapGPU参数();
	void f_resizeGPU参数();



protected:
	int32 m_纹理绑定计数;
private:
	

};









